package io.openkunlun.javadsl.springboot.server;

import io.openkunlun.javadsl.DaprExceptionResolver;
import io.openkunlun.javadsl.client.DaprClient;
import io.openkunlun.javadsl.server.DaprHandler;
import io.openkunlun.javadsl.server.DaprServer;
import io.openkunlun.javadsl.server.FailureDetector;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Role;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.annotation.Resource;
import java.io.IOException;
import java.util.Map;

@Configuration
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
@EnableConfigurationProperties(DaprServerProperties.class)
public class DaprServerConfigurator {

    @Resource
    private ApplicationContext applicationContext;
    @Resource
    private DaprServerProperties properties;

    @Resource
    private DaprClient daprClient;
    private DaprServer daprServer;

    @PostConstruct
    public void init() throws IOException {
        Map<String, DaprHandler> handlers = applicationContext.getBeansOfType(DaprHandler.class);
        DaprExceptionResolver errorHandler = applicationContext.getBean(DaprExceptionResolver.class);
        FailureDetector failureDetector = applicationContext.getBean(FailureDetector.class);
        daprServer = DaprServer
                .forAddress(daprClient, properties.getHost(), properties.getPort())
                .setId(properties.getId())
                .setTtl(properties.getTtl())
                .setWeight(properties.getWeight())
                .setWarmup(properties.getWarmup())
                .failureDetector(failureDetector)
                .addHandlers(handlers.values().toArray(new DaprHandler[]{}))
                .errorHandler(errorHandler)
                .build();
        daprServer.start();
    }

    @PreDestroy
    public void destroy() {
        if (daprServer != null) {
            daprServer.stop();
        }
    }

    @Bean(name = "daprServerListener")
    @ConditionalOnMissingBean
    DaprServerListener listener() {
        return new DaprServerListener();
    }
}
